package com.chagee.store.operation.server.service;

import cn.afterturn.easypoi.entity.vo.NormalExcelConstants;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chagee.store.operation.api.enums.*;
import com.chagee.store.operation.api.request.WorkOrderRequest;
import com.chagee.store.operation.api.response.WorkOrderResponse;
import com.chagee.store.operation.common.constant.CommonConstant;
import com.chagee.store.operation.common.enums.EvaluateTypeEnum;
import com.chagee.store.operation.common.exception.BizErrorCode;
import com.chagee.store.operation.common.exception.BizException;
import com.chagee.store.operation.common.utils.CommonUtil;
import com.chagee.store.operation.server.component.ReportExportCellWriteHandler;
import com.chagee.store.operation.server.config.EvaluateDictConfig;
import com.chagee.store.operation.server.entity.StoreOrderEvaluateDO;
import com.chagee.store.operation.server.entity.WorkOrderDO;
import com.chagee.store.operation.server.event.service.*;
import com.chagee.store.operation.server.model.param.QueryEvaluateListParam;
import com.chagee.store.operation.server.model.param.StoreInfoParam;
import com.chagee.store.operation.server.model.vo.*;
import com.chagee.store.operation.server.service.biz.WorkOrderBizService;
import com.chagee.store.operation.server.utils.DateUtil;
import com.chagee.storeManagement.api.event.enums.StoreCategoryEnum;
import com.personnel.auth.service.PersonnelAuthService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author : hk
 * @Date : 2024/4/25
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class StoreOrderEvaluateService {

	private static final int EXPORT_PAGE_SIZE = 200;
	@Resource
	private TaskExecutionBaseService taskExecutionBaseService;
	@Resource
	private StoreTaskRelationBaseService storeTaskRelationBaseService;
	@Resource
	private BasicTaskConfigurationService basicTaskConfigurationService;
	@Resource
	private WorkOrderReceiverBaseService workOrderReceiverBaseService;
	@Resource
	private PersonnelAuthService personnelAuthService;
	@Resource
	private StoreOrderDeviceBaseService storeOrderDeviceBaseService;
	@Resource
	private WorkOrderBaseService workOrderBaseService;
	@Resource
	private StoreOrderEvaluateBaseService storeOrderEvaluateBaseService;
	@Resource
	private EvaluateDictConfig evaluateDictConfig;

	@Resource
	private WorkOrderBizService workOrderBizService;

	private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

	public List<EvaluateInfoResponse> list(QueryEvaluateListParam param) {
		LambdaQueryWrapper<StoreOrderEvaluateDO> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(StoreOrderEvaluateDO::getWorkOrderNumber, param.getWorkOrderNumber());
		//queryWrapper.notIn(StoreOrderEvaluateDO::getEvaluateType, Arrays.asList("1"));
		List<StoreOrderEvaluateDO> list = storeOrderEvaluateBaseService.list(queryWrapper);

		List<EvaluateInfoResponse> arrayList = new ArrayList<>();
		for (StoreOrderEvaluateDO storeOrderEvaluateDO : list) {
			EvaluateInfoResponse evaluateInfoResponse = new EvaluateInfoResponse();
			evaluateInfoResponse.setId(storeOrderEvaluateDO.getId());
			evaluateInfoResponse.setWorkOrderNumber(storeOrderEvaluateDO.getWorkOrderNumber());
			evaluateInfoResponse.setStoreCode(storeOrderEvaluateDO.getStoreCode());
			//evaluateInfoResponse.setEvaluateScore(storeOrderEvaluateDO.getEvaluateScore());
			evaluateInfoResponse.setEvaluate(storeOrderEvaluateDO.getEvaluate());
			evaluateInfoResponse.setEvaluateCode(storeOrderEvaluateDO.getEvaluateCode());
			evaluateInfoResponse.setEvaluateType(storeOrderEvaluateDO.getEvaluateType());
			String evaluateType = getEvaluateType(storeOrderEvaluateDO);
			evaluateInfoResponse.setEvaluateTypeValue(evaluateType);
			evaluateInfoResponse.setEvaluateResult(storeOrderEvaluateDO.getEvaluateResult());
			evaluateInfoResponse.setRemark(storeOrderEvaluateDO.getRemark());
			arrayList.add(evaluateInfoResponse);
		}
		return arrayList;
	}

	@SneakyThrows
	public void evaluateExport(WorkOrderRequest requestParam, HttpServletRequest request, HttpServletResponse response, ModelMap map) {

		if (Objects.isNull(requestParam) || StringUtils.isBlank(requestParam.getCreateTimeStart()) || StringUtils.isBlank(requestParam.getCreateTimeEnd())) {
			throw new BizException(BizErrorCode.EXPORT_DATE_FAIL);
		}
		if (!DateUtil.getDistanceDate(requestParam.getCreateTimeStart(),requestParam.getCreateTimeEnd())) {
			throw new BizException(BizErrorCode.EXPORT_DISTANCE_DATE_FAIL);
		}

		CommonUtil.download(response, CommonConstant.THIRD_WORK_ORDER);
		try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), WorkOrderEvaluateExcelVO.class).build()) {
			WriteSheet writeSheet = EasyExcel.writerSheet(CommonConstant.THIRD_WORK_ORDER).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
				.registerWriteHandler(new ReportExportCellWriteHandler(CommonConstant.THIRD_WORK_ORDER)).build();

			Page<WorkOrderDO> page = new Page<>();
			page.setSize(EXPORT_PAGE_SIZE);
			int pageNum = 1;
			int currentSize = EXPORT_PAGE_SIZE;
			while (currentSize >= EXPORT_PAGE_SIZE) {
				page.setCurrent(pageNum++);
				Page<WorkOrderDO> workOrderDOPage = workOrderBizService.queryWorkOrderPage(page, requestParam);
				currentSize = workOrderDOPage.getRecords().size();
				if (CollectionUtils.isEmpty(workOrderDOPage.getRecords())) {
					excelWriter.write(new ArrayList<WorkOrderEvaluateExcelVO>(), writeSheet);
					break;
				}
				List<String> orderNoList = workOrderDOPage.getRecords().stream().map(WorkOrderDO::getWorkOrderNumber).collect(Collectors.toList());
				List<StoreOrderEvaluateDO> storeOrderEvaluateDOS = storeOrderEvaluateBaseService.selectEvaluateList(orderNoList);
				List<WorkOrderEvaluateExcelVO> workOrderEvaluateExcelVOS = convertEvaluate(storeOrderEvaluateDOS, workOrderDOPage.getRecords());
				excelWriter.write(workOrderEvaluateExcelVOS, writeSheet);
			}
		}
	}

	public List<WorkOrderEvaluateExcelVO> convertEvaluate(List<StoreOrderEvaluateDO> storeOrderEvaluateDOS, List<WorkOrderDO> workOrderDOS) {
		if (CollectionUtils.isEmpty(storeOrderEvaluateDOS)) {
			return new ArrayList<>();
		}
		List<WorkOrderEvaluateExcelVO> workOrderResponseList = new LinkedList<>();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		if (CollUtil.isNotEmpty(workOrderDOS)) {
			Map<String, WorkOrderDO> workOrderDOMap = workOrderDOS.stream().collect(Collectors.toMap(WorkOrderDO::getWorkOrderNumber, Function.identity(), (a, b) -> a));
			for (StoreOrderEvaluateDO storeOrderEvaluateDO : storeOrderEvaluateDOS) {
				WorkOrderEvaluateExcelVO evaluateExcelVO = new WorkOrderEvaluateExcelVO();
				WorkOrderDO workOrderDO = workOrderDOMap.get(storeOrderEvaluateDO.getWorkOrderNumber());
				if (Objects.nonNull(workOrderDO)) {
					evaluateExcelVO.setWorkOrderNumber(workOrderDO.getWorkOrderNumber());
					evaluateExcelVO.setStoreCode(workOrderDO.getStoreCode());
					evaluateExcelVO.setStoreName(workOrderDO.getStoreName());
					evaluateExcelVO.setDocumentType(OrderStatusEnum.getByType(workOrderDO.getDocumentType()).getDesc());
					evaluateExcelVO.setDocumentScore(workOrderDO.getDocumentScore());
					if (StringUtils.isNotBlank(workOrderDO.getReceiver()) && StringUtils.isNotBlank(workOrderDO.getReceiverMobile())) {
						String[] receiver = workOrderDO.getReceiver().split(",");
						String[] receiverMobile = workOrderDO.getReceiverMobile().split(",");

						List<String> encryptPhoneList = new ArrayList<>();
						for (String phone : receiverMobile) {
							String phoneNumber = phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
							encryptPhoneList.add(phoneNumber);
						}
						receiverMobile = encryptPhoneList.toArray(new String[0]);
						String result = joinStringArrays(receiver, receiverMobile);
						evaluateExcelVO.setReceiver(result);
					}
					evaluateExcelVO.setSupplier(workOrderDO.getSupplier());
					evaluateExcelVO.setStoreCategory(StoreCategoryEnum.queryByType(workOrderDO.getStoreCategory()).getDesc());
					evaluateExcelVO.setCompanyName(workOrderDO.getCompanyName());
					evaluateExcelVO.setBusinessName(workOrderDO.getBusinessName());
					String createTime = dateFormat.format(storeOrderEvaluateDO.getCreateTime());
					evaluateExcelVO.setCreateTime(createTime);
					evaluateExcelVO.setEvaluate(storeOrderEvaluateDO.getEvaluate());
					String evaluateType = getEvaluateType(storeOrderEvaluateDO);
					evaluateExcelVO.setEvaluateType(evaluateType);
					evaluateExcelVO.setEvaluateResult(storeOrderEvaluateDO.getEvaluateResult());
					evaluateExcelVO.setRemark(storeOrderEvaluateDO.getRemark());
				}
				workOrderResponseList.add(evaluateExcelVO);
			}
		}
		return workOrderResponseList;
	}

	private static String joinStringArrays(String[] name, String[] phone) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < name.length; i++) {
			sb.append(name[i]).append("(").append(phone[i % phone.length]).append("),");
		}
		return sb.deleteCharAt(sb.lastIndexOf(",")).toString();
	}

	private String getEvaluateType(StoreOrderEvaluateDO storeOrderEvaluateDO){
		//兼容旧数据
		String evaluateType = "";
		EvaluateTypeEnum evaluateTypeEnum = EvaluateTypeEnum.queryByType(storeOrderEvaluateDO.getEvaluateType());
		if (null == evaluateTypeEnum){
			CommentTypeEnum commentTypeEnum = CommentTypeEnum.queryByType(storeOrderEvaluateDO.getEvaluateType());
			if (null != commentTypeEnum){
				evaluateType = commentTypeEnum.getDesc();
			}
		}else {
			evaluateType = evaluateTypeEnum.getDesc();
		}
		return evaluateType;
	}

}
